package com.zq.sdklib.transform.cost.asm

import javassist.CannotCompileException
import javassist.NotFoundException
import org.objectweb.asm.*
import java.io.File
import java.io.FileInputStream
import java.io.FileOutputStream

class AsmMethodCostUtil {
    companion object {
        fun injectCostForFile(file: File){
            try {
                println("处理: $file")
                var writer: ClassWriter? = null
                FileInputStream(file).use { fis ->
                    val reader = ClassReader(fis)
                    writer = ClassWriter(reader, ClassWriter.COMPUTE_MAXS)
                    //visitor 所做的修改会勇敢writer 去操作修改
                    val visitor = AsmMethodCostClassVisitor(Opcodes.ASM9, writer)
                    reader.accept(visitor, ClassReader.EXPAND_FRAMES)
                }
                if(writer != null){
                    FileOutputStream(file).use { fos ->
                        fos.write(writer!!.toByteArray())
                    }
                }
            }catch (e:Exception){
                e.printStackTrace()
            }
        }


        @kotlin.jvm.Throws(NotFoundException::class, CannotCompileException::class)
        fun traverseFile(baseDir: File) {
            val fs = baseDir.listFiles()
            for (f in fs) {
                if (f.isDirectory) {    //若是目录，则递归
                    if (f.name.contains("META-INF")) {

                        continue
                    }
                    traverseFile(f)
                } else if (f.isFile) {
                    if (isNeedTraceFile(f.name)) {
                        //代码插入
                        injectCostForFile(f)
                    }
                }
            }
        }


        private val UN_TRACE_CLASS = arrayOf("R.class", "R$", "Manifest", "BuildConfig")

        fun isNeedTraceFile(fileName: String): Boolean {
            if (fileName.endsWith(".class")) {
                for (unTraceCls in UN_TRACE_CLASS) {
                    if (fileName.contains(unTraceCls)) {
                        return false
                    }
                }
            } else {
                return false
            }
            return true
        }
    }
}